package service

import (
	"fmt"
	"github.com/sirupsen/logrus"
	"miao-wails/backed/app/dao"
	"miao-wails/backed/lib/id"
	"miao-wails/backed/lib/utils"
	"miao-wails/backed/structs/base"
	"miao-wails/backed/structs/tables"
	"strings"
	"time"
)

var SecTextSer = new(secretTextService)

type secretTextService struct{}

func (s secretTextService) AddSecretKey(in base.AddSecretKey) (err error) {
	var content string
	content, err = s.getSecretContent(in.Algorithm)
	if err != nil {
		return err
	}
	m := tables.SecretKey{
		Id:        id.GetSnowId(),
		Title:     in.Title,
		Remark:    in.Remark,
		Algorithm: in.Algorithm,
		Content:   content,
		CreatedAt: time.Now().Unix(),
	}
	err = dao.SecretKeyDao.CreateKey(m)
	return err
}

func (s secretTextService) GetSecretKeyList() (li []tables.SecretKey, err error) {
	return dao.SecretKeyDao.FindKeys()
}

func (s secretTextService) DelSecretKey(id int64) (err error) {
	var (
		num int64
	)
	num, err = dao.SecretKeyDao.CountTextMapKey(id)
	if err != nil {
		return err
	}
	if num > 0 {
		err = fmt.Errorf("使用中的密钥不能删除！")
		return err
	}
	err = dao.SecretKeyDao.DelKeyById(id)
	return err
}

func (s secretTextService) AddText(in base.AddSecretText) (err error) {
	// 处理内容
	var (
		con string
		sk  tables.SecretKey
	)
	sk, err = dao.SecretKeyDao.FindKeyById(utils.StrToInt64(in.KeyId))
	if err != nil {
		return err
	}
	con, err = s.encryption(in.Content, sk)
	if err != nil {
		return err
	}
	m := tables.SecretText{
		Id:        id.GetSnowId(),
		Title:     in.Title,
		Label:     in.Label,
		TextType:  in.TextType,
		Content:   con,
		KeyId:     utils.StrToInt64(in.KeyId),
		AdminKey:  in.AdminKey,
		Prompt:    in.Prompt,
		IsPrivate: in.IsPrivate,
		CreatedAt: time.Now().Unix(),
	}
	err = dao.SecretKeyDao.CreateText(m)
	return err
}

func (s secretTextService) GetTextList(isPrivate bool) (li []tables.SecretText, err error) {
	return dao.SecretKeyDao.FindTextList(isPrivate)
}

func (s secretTextService) DelText(id int64, adminKey string) (err error) {
	var (
		m tables.SecretText
	)
	m, err = dao.SecretKeyDao.FindTextById(id)
	if err != nil {
		return err
	}
	if m.AdminKey != adminKey {
		err = fmt.Errorf("密码不正确")
		return err
	}
	err = dao.SecretKeyDao.DelTextById(id)
	return err
}
func (s secretTextService) UpdateText(in base.UpdateSecretText) (err error) {
	var (
		m tables.SecretText
	)
	m, err = dao.SecretKeyDao.FindTextById(in.Id)
	if err != nil {
		return err
	}
	if m.AdminKey != in.CurrentAdminKey {
		err = fmt.Errorf("密码不正确")
		return err
	}
	m.Title = in.Title
	m.Label = in.Label
	m.AdminKey = in.AdminKey
	m.Prompt = in.Prompt
	m.IsPrivate = in.IsPrivate
	err = dao.SecretKeyDao.UpdateTextById(m)
	return err
}

func (s secretTextService) GetTextContent(id int64, adminKey string) (textDetail base.SecretTextContent, err error) {
	var (
		st tables.SecretText
		sk tables.SecretKey
	)
	st, err = dao.SecretKeyDao.FindTextById(id)
	if err != nil {
		return
	}
	sk, err = dao.SecretKeyDao.FindKeyById(st.KeyId)
	if err != nil {
		return
	}
	if st.AdminKey != adminKey {
		err = fmt.Errorf("密码不正确")
		return
	}
	chapterList := make([]base.ChapterInfo, 0)
	switch st.TextType {
	case "simple":
		fallthrough
	case "doc":
		chapterList = append(chapterList, base.ChapterInfo{
			ChapterId: 0,
			Title:     st.Title,
			Content:   s.decrypt(st.Content, sk),
		})
	case "chapter":
		var li []tables.SecretChapter
		li, err = dao.SecretKeyDao.FindChapterList(st.Id)
		if err != nil {
			return
		}
		for _, item := range li {
			chapterList = append(chapterList, base.ChapterInfo{
				ChapterId: item.Id,
				Title:     item.Title,
				Content:   s.decrypt(item.Content, sk),
			})
		}
	default:
		err = fmt.Errorf("不合法的密钥信息")
	}
	textDetail = base.SecretTextContent{
		TextId:      st.Id,
		TextTitle:   st.Title,
		ChapterList: chapterList,
	}
	return
}

func (s secretTextService) UpdateTextContent(tid int64, conStr string) (err error) {
	var (
		st tables.SecretText
		sk tables.SecretKey
	)
	st, err = dao.SecretKeyDao.FindTextById(tid)
	if err != nil {
		return
	}
	sk, err = dao.SecretKeyDao.FindKeyById(st.KeyId)
	if err != nil {
		return
	}
	var encStr string
	encStr, err = s.encryption(conStr, sk)
	if err != nil {
		return
	}
	st.Content = encStr
	err = dao.SecretKeyDao.UpdateTextById(st)
	return err
}
func (s secretTextService) AddChapter(tid int64, title string, conStr string) (err error) {
	var (
		st tables.SecretText
		sk tables.SecretKey
	)
	st, err = dao.SecretKeyDao.FindTextById(tid)
	if err != nil {
		return
	}
	sk, err = dao.SecretKeyDao.FindKeyById(st.KeyId)
	if err != nil {
		return
	}
	var encStr string
	encStr, err = s.encryption(conStr, sk)
	if err != nil {
		return
	}
	err = dao.SecretKeyDao.CreateChapter(tables.SecretChapter{
		Id:      id.GetSnowId(),
		TextId:  tid,
		Title:   title,
		Content: encStr,
	})
	return err
}

func (s secretTextService) DelChapter(tid int64, cid int64, adminKey string) (err error) {
	var (
		m tables.SecretText
	)
	m, err = dao.SecretKeyDao.FindTextById(tid)
	if err != nil {
		return err
	}
	if m.AdminKey != adminKey {
		err = fmt.Errorf("密码不正确")
		return err
	}
	err = dao.SecretKeyDao.DelChapterById(cid)
	return err
}

// encryption 对内容进行加密
func (s secretTextService) encryption(in string, sk tables.SecretKey) (str string, err error) {
	switch sk.Algorithm {
	case "simple":
		str = in
	case "AES":
		arr := strings.Split(sk.Content, "-")
		if len(arr) != 2 {
			err = fmt.Errorf("不合法的密钥信息")
			return
		}
		str, err = utils.AesUtils.Encrypt(in, arr[0], arr[1])
	default:
		err = fmt.Errorf("未知密钥类型")
	}
	return
}

// decrypt 解密内容
func (s secretTextService) decrypt(in string, sk tables.SecretKey) (str string) {
	var err error
	switch sk.Algorithm {
	case "simple":
		str = in
	case "AES":
		arr := strings.Split(sk.Content, "-")
		if len(arr) != 2 {
			logrus.Errorf("不合法的密钥信息")
			return
		}
		str, err = utils.AesUtils.Decrypt(in, arr[0], arr[1])
		if err != nil {
			logrus.Errorf("不合法的密钥信息")
			return
		}
	default:
		logrus.Error("未知密钥类型")
	}
	return
}

func (s secretTextService) getSecretContent(algorithm string) (str string, err error) {
	switch algorithm {
	case "AES":
		var (
			key string
			vi  string
		)
		key, err = utils.AesUtils.GenerateKey()
		if err != nil {
			return
		}
		vi, err = utils.AesUtils.GenerateIV()
		if err != nil {
			return
		}
		str = fmt.Sprintf("%s-%s", key, vi)
	default:
		str = ""
	}
	return
}
